﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PSE.ProcessManager.Entity;
using System.Threading;

namespace PSE.ProcessManager.ResourceAccess.FileSystemProvider
{
    internal class LogResourceAccess : BaseFileAccess
    {
        private static Mutex _mtxLock = new Mutex(false, "PSE.ProcessManager.ResourceAccess.FileSystemProvider.Message.MtxLock");

        private string _filePath;

        public LogResourceAccess(string filePath)
        {
            _filePath = filePath;
        }

        internal List<LogEntity> GetAll()
        {
            List<LogEntity> result = base.LoadFromXmlFile<List<LogEntity>>(_filePath);

            if (result == null)
                result = new List<LogEntity>();

            return result;
        }

        internal List<LogEntity> GetAll(int processId)
        {
            List<LogEntity> result = base.LoadFromXmlFile<List<LogEntity>>(_filePath);

            if (result.Count > 0)
                return result.FindAll(im => im.ProcessID == processId);
            else
                return new List<LogEntity>();
        }

        internal LogEntity GetLast(int processId)
        {
            List<LogEntity> result = GetAll();

            result.Sort(new Comparison<LogEntity>(CompareLogByStartDate));

            return result.Last<LogEntity>();
        }

        internal int Insert(LogEntity entity)
        {
            int idLog = 0;

            try
            {
                _mtxLock.WaitOne();

                List<LogEntity> messages = GetAll();

                entity.Id = GetNextLogId(messages);

                messages.Add(entity);

                base.SaveToXmlFile(_filePath, messages);

                idLog = entity.Id;
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }

            return idLog;
        }

        internal void Update(int idLog, DateTime endDate)
        {
            try
            {
                _mtxLock.WaitOne();

                List<LogEntity> messagesInFile = GetAll();

                int index = messagesInFile.FindIndex(m => m.Id == idLog);
                
                if (index >= 0)
                {
                    messagesInFile[index].EndDate = endDate;
                    
                    base.SaveToXmlFile(_filePath, messagesInFile);
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        internal void Update(int idLog, DateTime endDate, string errorMessage)
        {
            try
            {
                _mtxLock.WaitOne();

                List<LogEntity> messagesInFile = GetAll();

                int index = messagesInFile.FindIndex(m => m.Id == idLog);

                if (index >= 0)
                {
                    messagesInFile[index].EndDate = endDate;
                    messagesInFile[index].ErrorMessage = errorMessage;

                    base.SaveToXmlFile(_filePath, messagesInFile);
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        internal void Delete(int logId)
        {
            try
            {
                _mtxLock.WaitOne();

                List<LogEntity> messages = GetAll();
                messages.RemoveAll(m => m.Id == logId);
                base.SaveToXmlFile(_filePath, messages);
            }
            catch
            {
                throw;
            }
            finally
            {
                _mtxLock.ReleaseMutex();
            }
        }

        private int GetNextLogId(List<LogEntity> logInfFile)
        {
            int id = 0;

            if (logInfFile.Count > 0)
            {
                logInfFile.Sort(new Comparison<LogEntity>(CompareLogById));
                id = logInfFile.Last<LogEntity>().Id;
            }
            
            return id + 1;
        }

        private int CompareLogById(LogEntity a, LogEntity b)
        {
            return a.Id.CompareTo(b.Id);
        }

        private int CompareLogByStartDate(LogEntity a, LogEntity b)
        {
            return a.StartDate.CompareTo(b.StartDate);
        }
    }
}
